let isDone:boolean=false;
let decLiteral:number=6;
let name:string="bob";
name="smith";
let named:string=`Gene`;
let age:number=37;
let sentence:string=`Hello, my name is ${ name }.
I'll be ${ age + 1 } years old next month.`
let list:number[]=[1,2,3];
let listed:Array<number>=[1,2,3];
//元组数组
let x:[string,number];
x=['hellow',10];
//枚举相当于
enum Color {Red,Green=2,Blue}
let c:Color=Color.Blue;
let colorName:string=Color[2];
let notSure:any=4;
notSure="maybe a string instead";
let lists:any[]=[1,true,'free'];
console.log(lists,'表达式')
//void表示没有任何返回值
function  warnUser():void{
    console.log('没有返回值')
}
warnUser()
let u:undefined=undefined;
let n:null=null;
function error(message:string):never{
    throw new Error(message)
}
let someValue:any="this is a string";
//类型断言字符串长度也就是
let strLength:number=(<string>someValue).length;
let strLengthed:number=(someValue as string).length
console.log(strLength,strLengthed,'字符串长度')
console.log(u,n)
//函数变量的声明
//下面的相当于是在接收参数的时候表明label需要为string类型
function printLabel(labelledObj:{label:string}){
    console.log(labelledObj.label)
}
//接口
interface LabelledValue{
    label:string
}
//定义接口
function printLabeled(labelledObj:LabelledValue){
    console.log(labelledObj.label)
}
let myobj={size:10,label:'Size 10 Object'};
printLabeled(myobj)
printLabel(myobj)
interface SquareConfig{
    color?:string;
    width?:number
}
//其中｛color:string;area:number｝是函数的返回值
function createSquare(config:SquareConfig):{color:string;area:number}{
    let newSquare={color:"white",area:100};
    if(config.color){
        newSquare.color=config.color;
    }
    if (config.width) {
        newSquare.area = config.width * config.width;
    }
    return newSquare;
}
let mySquare = createSquare({color: "black"});
console.log(mySquare,'宽度表达')
interface Point{
    x:number;
    y:number
}
let p1:Point={x:10,y:20};
//定义函数接口
interface SearchFunc{
    (source: string, subString: string): boolean;
}
let mySearch:SearchFunc;
mySearch=function (src,sub){
    let resulrt=src.search(sub);
    return resulrt>-1
}
var Node=mySearch('1111','11');
console.log(Node,'节点')
//索引类型
interface StringArray{
    [index:number]:string
}
let myArray:StringArray;
myArray=['BOb','Fred'];
let myStr: string = myArray[0];
console.log(myStr,'列表')
//为构造函数所用
interface ClockConstructor {
    new (hour: number, minute: number): ClockInterface;
}
interface ClockInterface {
    tick();
}

function createClock(ctor: ClockConstructor, hour: number, minute: number): ClockInterface {
    return new ctor(hour, minute);
}

class DigitalClock implements ClockInterface {
    constructor(h: number, m: number) { }
    tick() {
        console.log("beep beep");
    }
}
class AnalogClock implements ClockInterface {
    constructor(h: number, m: number) { }
    tick() {
        console.log("tick tock");
    }
}

let digital = createClock(DigitalClock, 12, 17);
let analog = createClock(AnalogClock, 7, 32);
//接口继承加类型断言
interface Shape{
    color:string;
}
interface Square extends Shape{
    sideLength:number
}
let square=<Square>{};
square.color="blue";
square.sideLength=10;
console.log(square)
class Greeter{
    greeting:string;
    constructor(message:string) {
        this.greeting=message
    }
    greet(){
        return 'Hello,'+this.greeting
    }
}
let greeter=new Greeter('world');
console.log(greeter.greet());
class Animal{
    move(distanceInMeters: number = 0){
        console.log(`Animal moved ${distanceInMeters}m.`);
    }
}
class Dog extends Animal{
    bark(){
        console.log('Woof!')
    }
}

const dog = new Dog();
dog.bark();
dog.move(10);
dog.bark();
class Animaled{
    name:string;
    constructor(theName:string) {
     this.name=theName
    }
    move(distanceInMeters: number = 0){
        console.log(`${this.name} moved ${distanceInMeters}m.`);
    }
}
class Snake extends Animaled{
    constructor(name:string) {
        super(name);
    }
    move(distanceInMeters = 5){
        console.log("Slithering...");
        super.move(distanceInMeters);
    }
}
class Horse extends Animaled{
    constructor(name:string) {
        super(name);
    }
    move(distanceInMeters=45){
        console.log("Galloping...");
        super.move(distanceInMeters);
    }}

let sam=new Snake('Sammy the Python');
let tom:Animal=new Horse("Tommy the Palomino");
sam.move();
tom.move(34);
class Person{
    protected name:string
    protected constructor(theName:string) {
        this.name=theName;
    }

}
//通过proteced可以被子类继承但是不能再外部定义
class Employee extends Person{
    private department:string;
    constructor(name:string,department:string) {
        super(name);
        this.department=department
    }
    public getElevatorPitch(){
        return `Hello, my name is ${this.name} and I work in ${this.department}.`;
    }
}
let howard=new Employee('Howard',"Sales");
console.log(howard.getElevatorPitch());
//这里面name是只读属性不能修改
class Octopus{
    readonly name:string;
    readonly numberOfLegs:number=8;
    constructor(theName: string) {
     this.name=theName
    }
}
let dad=new Octopus('Man with the 8 strong legs');
let passcode="secr1et passcode";
//用到了set和get的方法
class Employeed{
    private _fullName: string;

    get fullName(): string {
        return this._fullName;
    }
    set fullName(newName:string){
        if(passcode&&passcode=='secret passcode'){
            this._fullName=newName;
        }else{
            console.log("Error: Unauthorized update of employee!");
        }
    }
}
let employeed=new Employeed();
employeed.fullName="Bob Smith";
if(employeed.fullName){
    alert(employeed.fullName)
}
//加入static相当于放入Grid当中
class Grid{
    static origin={x:0,y:0};
    calculateDistanceFromOrigin(point:{x:number;y:number}){
        let xDist=(point.x-Grid.origin.x);
        let yDist=(point.y-Grid.origin.y);
        return Math.sqrt(xDist * xDist + yDist * yDist) / this.scale;
    }
    constructor (public scale: number) { }
}
let grid1 = new Grid(1.0);  // 1x scale
let grid2 = new Grid(5.0);  // 5x scale

console.log(grid1.calculateDistanceFromOrigin({x: 10, y: 10}));
console.log(grid2.calculateDistanceFromOrigin({x: 10, y: 10}));
//为抽象类，抽象类不可被定义不过可以被继承使用
abstract class Department{
    constructor(public name:string) {
    }
    printName():void{
        console.log('Department name: ' + this.name);
    }
    abstract printMeeting():void;//这个是抽象方法必须要在派生类实现
}
class AccountingDepartment extends Department{
    constructor() {
        super('Accounting and Auditing');
    }
   printMeeting():void {
       console.log('The Accounting Department meets each Monday at 10am.');
   }
    generateReports(): void {
        console.log('Generating accounting reports...');
    }
}
let department:Department;
department=new AccountingDepartment();
department.printMeeting();
department.printName()
class Point{
    x:number;
    y:number;
}
interface Point3d extends Point{
    z:number
}
let point3d:Point3d={x:1,y:2,z:3}
//为函数定义类型
function add(x:number,y:number):number{
    return x+y
}
let myAdd=function (x:number,y:number):number{
    return x+y
}
function buildName(firstName:string,lastName?:string){
    if(lastName){
        return firstName+''+lastName
    }else{
        return firstName
    }
}
let result3 = buildName("Bob", "Adams");
console.log(result3,'结果')
function buildNames(firstName:string,...resetofName:string[]){
    return firstName+''+resetofName.join("")
}
let employeeName = buildNames("Joseph", "Samuel", "Lucas", "MacKinzie");
//在下面将下面的this改成其对象了
let deck = {
    suits: ["hearts", "spades", "clubs", "diamonds"],
    cards: Array(52),
    createCardPicker: function() {
        // NOTE: the line below is now an arrow function, allowing us to capture 'this' right here
        return () => {
            let pickedCard = Math.floor(Math.random() * 52);
            let pickedSuit = Math.floor(pickedCard / 13);

            return {suit: this.suits[pickedSuit], card: pickedCard % 13};
        }
    }
}

let cardPicker = deck.createCardPicker();
let pickedCard = cardPicker();

alert("card: " + pickedCard.card + " of " + pickedCard.suit);
function identity<T>(arg:T):T{
    return arg
}
var ident=identity<number>(11);
console.log(ident,'列表')
interface Counter {
    (start: number): string;
    interval: number;
    reset(): void;
}

function getCounter(): Counter {
    let counter = <Counter>function (start: number) { };
    console.log(counter,'什么类型')
    counter.interval = 123;
    counter.reset = function () { };
    return counter;
}

let cNode = getCounter();
cNode(10);
cNode.reset();
//用来定义数组类型
//下面被称为泛型也就是传递的数值需要跟返回的数值保持一返回的类型和传递的类型需要相同
function loggingIdentity<T>(arg:Array<T>):Array<T>{
    console.log(arg.length);
    return arg;
}
loggingIdentity<Array>([1,2,3]);
function identityed<T>(arg:T):T{
    return arg;
}
interface GenericIdentityFn{
    <T>(arg:T):T;
}
let myIdentity:<T>(arg:T)=>T=identityed;
console.log(myIdentity<string>('222'),'赋值变量')
let myIdentityed:{<T>(arg:T):T}=identityed;
console.log(myIdentityed,'呵呵');
let myIdentitys: GenericIdentityFn = identityed;
console.log(myIdentitys,'参数类型')
interface GenericIdentityFns<T> {
    (arg: T): T;
}

function identityList<T>(arg: T): T {
    return arg;
}

let myIdentityedNode: GenericIdentityFns<number> = identityList;
console.log(myIdentityedNode,'青银')
function createArray<T>(length:number,value:T):Array<T>{
    let result:T[]=[];
    for(let i=0;i<length;i++){
        result[i] = value;
    }
    return result
}
let string=createArray<string>(3,'x')
console.log(string,'字符串')
class GenericNumber<T>{
    zeroValue:T
}
